//@author A0101906R
#include "CmdMark.h"

using namespace Twentyfifth;
using namespace std;

const std::string CmdMark::FEEDBACK_MARK_DONE = "Task successfully marked as done.";
const std::string CmdMark::FEEDBACK_MARK_UNDONE = "Task successfully marked as undone.";
const std::string CmdMark::FEEDBACK_UNDOMARKOK = "Undo mark successful.\n";
const std::string CmdMark::ERROR_MARKTIMEDTASK = "Only floating tasks and deadline tasks can be marked done/undone.\n";
//@author A0101906R
CmdMark::CmdMark() {
	cmdType = MARK;
}
//@author A0101906R
Status CmdMark::execution() {
	Status markStatus;
	Status tempS;
	assert(storage != NULL);
	int id;
	bool previousState;

	id = task.getId();

	try {
		rememberTask(tempS);

		previousState = (storage->viewTask(id)).tasks[0].isDone();
		previousState = !previousState;
		markStatus = storage->editTask(id, DONE, previousState);

		task = taskBeforeMark;
		setDescForMark(markStatus, previousState);
	}
	catch (string error) {
		markStatus.desc = error;
	}
	return markStatus;
}
//@author A0101906R
Status CmdMark::undo(Status::StatusCode c) {
	Status undoStatus;
	bool previousState;
	assert(storage != NULL);
	try {
		if (c != Status::OK) {
			throw ERROR_UNSUCCESSFUL;
		}
		int id = task.getId();
		previousState = task.isDone();
		undoStatus = storage->editTask(id, DONE, previousState);

		setDescForUndo(undoStatus);

	}
	catch (string error) {
		undoStatus.desc = error;
	}
	return undoStatus;
}
//@author A0101906R
void CmdMark::rememberTask(Status& s) {
	int id;
	id = task.getId();

	s = storage->viewTask(id);

	if (s.code != Status::OK) {
		s.desc = statusCodeToString(s);
		throw s.desc;
	}

	if ((s.tasks[0]).getTaskType() == Task::TIMED_TASK) {
		throw ERROR_MARKTIMEDTASK;
	}

	if (s.code == Status::OK) {
		assert(s.tasks.size() != 0);
		taskBeforeMark = s.tasks[0];
	}
	return;
}
//@author A0101906R
void CmdMark::setDescForMark(Status& s, bool state) {
	if (s.code == Status::OK) {
		if (state) {
			s.desc = FEEDBACK_MARK_DONE;
		} else {
			s.desc = FEEDBACK_MARK_UNDONE;
		}
	} else {
		s.desc = statusCodeToString(s);
	}
	return;
}
//@author A0101906R
void CmdMark::setDescForUndo(Status& s) {
	if (s.code == Status::OK) {
		s.desc = FEEDBACK_UNDOMARKOK;
	} else {
		s.desc = statusCodeToString(s);
	}
	return;
}